from flask import jsonify, current_app
from apps.interface.models.interfaceapimsg import InterfaceApiMsg
from apps.interface.models.interfacecasedata import InterfaceCaseData
from apps.interface.models.interfacecase import InterfaceCase
from library.api.db import db


class InterfaceSyncBusiness(object):
    
    @classmethod
    def get_sync_interface(cls, api_id):
        try:
            interface_api_msg = InterfaceApiMsg.query.filter_by(id=api_id).first()
            # 如果api表查不出数据，返回[]
            if not interface_api_msg:
                return 0, [], 0, '成功'
            api_encryption = interface_api_msg.encryption
            # 如果无md5(老数据)，则返回[]
            if not api_encryption:
                return 0, [], 0, '成功'
            # 获取有效的case_data的接口信息数据,无数据返回[]
            case_data = InterfaceSyncBusiness.according_api_id_find_case_data(api_id)
            if not case_data:
                return 0, [], 0, '成功'
            base_case_data = InterfaceSyncBusiness.filter_del_case(case_data)
            if not base_case_data:
                return 0, [], 0, '成功'
            # 获取最终case_data的接口信息数据
            base_case_data = InterfaceCaseData.query.filter(
                InterfaceCaseData.case_id.in_(base_case_data),
                InterfaceCaseData.api_msg_id == api_id).all()
            # 新建空集合
            dict_ids = set()
            # 所有 case_data 数据
            for x in base_case_data:
                # 如果接口信息和接口用例md5不一样
                if x.encryption != api_encryption:
                    dict_ids.add(x.case_id)
            # id、name以字典形式传入列表
            case_dict = [{'case_id': case_id,
                          'case_name': InterfaceCase.query.filter_by(id=case_id).first().name,
                          'api_id': api_id} for case_id in dict_ids]
            # 获取需同步用例个数
            total = len(case_dict)
            current_app.logger.info(case_dict)
            return 0, case_dict, total, '成功'
        except Exception as e:
            current_app.logger.info(str(e))
            return 101, [str(e)], 0, '获取列表失败'
    
    @classmethod
    def according_api_id_find_case_data(cls, api_id):
        """
        根据api_id获取有效的case_data数据
        :param api_id:
        :return: case_data: [case_id]
        """
        # 取所有接口信息id、name(过滤已删除的case_data数据)
        interface_case_data = InterfaceCaseData.query.filter_by(api_msg_id=api_id,
                                                                status='true',
                                                                execute_status=0).all()
        # 没有数据返回None
        if not interface_case_data:
            return None
        case_data = [x.case_id for x in interface_case_data]
        return case_data
    
    @classmethod
    def filter_del_case(cls, case_id_list):
        """
        过滤已删除的case,返回一个list,
        :param case_id_list:case_id
        :return: base_case_id:case_id
        """
        # 过滤已删除的case_id
        case = InterfaceCase.query.filter(InterfaceCase.id.in_(case_id_list),
                                          InterfaceCase.status == 0).all()
        if not case:
            return None
        base_case_id = [base_case_id.id for base_case_id in case]
        return base_case_id
    
    @classmethod
    def update_case_data(cls, case_ids, api_id):
        try:
            # modified_
            api_data = InterfaceApiMsg.query.filter_by(id=api_id).first()
            # 获取接口信息的数据
            # 同步忽略提取、断言
            api_data = {
                'header': api_data.header,
                'variable': api_data.variable,
                'json_variable': api_data.json_variable,
                'encryption': api_data.encryption,
                'param': api_data.param
            }
            for case_id in case_ids:
                # 获取接口信息对应的所有接口用例
                case_data = InterfaceCaseData.query.filter_by(api_msg_id=api_id,
                                                              case_id=case_id).all()
                # 遍历用例下每条接口信息
                for case_ids in case_data:
                    case_id = case_ids.id
                    m = InterfaceCaseData.query.get(case_id)
                    # 替换header、variable、json_variable、md5、param加密数据
                    m.header = api_data['header']
                    m.variable = api_data['variable']
                    m.json_variable = api_data['json_variable']
                    m.encryption = api_data['encryption']
                    m.param = api_data['param']
                    db.session.add(m)
                db.session.commit()
            sync = cls.contrast_encryption(api_id, api_data['encryption'])
            # 如果为0，则不需要同步
            if sync == 0:
                c = InterfaceApiMsg.query.get(api_id)
                c.is_sync = sync
                db.session.add(c)
                db.session.commit()
            return 'ok', 0
        
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(str(e))
        return 0
    
    @classmethod
    def contrast_encryption(cls, api_id, base_encryption):
        """
        修改、同步用例获取接口信息与用例同步状态
        :param api_id:
        :param base_encryption:
        :return: is_sync
        """
        if not api_id:
            raise jsonify({'msg': 'api_id不能为空', 'status': 0})
        # 如果md5都相等 则为0
        is_sync = 0
        # 获取有效的case_data
        case_data = cls.according_api_id_find_case_data(api_id)
        # 如果没有有效的case_data，不需更新
        if not case_data:
            return is_sync
        # 获取有效的case_id
        case_id = InterfaceSyncBusiness.filter_del_case(case_data)
        case_datas = InterfaceCaseData.query.filter(InterfaceCaseData.api_msg_id == api_id,
                                                    InterfaceCaseData.case_id.in_(
                                                        case_id)).all()
        if case_datas:
            # 遍历case_data所有的encryption
            for case_data in case_datas:
                new_encryption = case_data.encryption
                if base_encryption != new_encryption:
                    is_sync = 1
                    break
        return is_sync
